import { Injectable } from '@nestjs/common';
import { ResourceInfo, ResourceType } from '../types/resource.types';
// 使用环境变量避免路径别名问题
const cdnDomain = process.env.CDN_DOMAIN || 'cdn.appthen.com';

@Injectable()
export class ResourceScannerService {
  // 只下载这些域名的资源
  private readonly allowedDomains = ['cdn.appthen.com', 'cdn.appthen.cn'];

  /**
   * 从项目数据中扫描所有资源
   */
  scanProjectResources(projectData: any, documents: any[]): ResourceInfo[] {
    const resources: ResourceInfo[] = [];

    // 1. 扫描项目本身的资源
    this.scanProjectScreenshots(projectData, resources);
    this.scanProjectAssets(projectData, resources);
    this.scanProjectDocuments(projectData, resources);

    // 2. 扫描文档中的资源
    documents.forEach(doc => {
      this.scanDocumentResources(doc, resources);
    });

    // 过滤只允许的域名
    const filteredResources = resources.filter(resource =>
      this.isAllowedDomain(resource.originalUrl) || this.isQiniuHash(resource.originalUrl)
    );

    // 去重
    return this.deduplicateResources(filteredResources);
  }

  /**
   * 检查是否为允许的域名
   */
  private isAllowedDomain(url: string): boolean {
    if (!url.startsWith('http://') && !url.startsWith('https://')) {
      return false; // 不是完整URL
    }

    try {
      const urlObj = new URL(url);
      return this.allowedDomains.includes(urlObj.hostname);
    } catch {
      return false;
    }
  }

  /**
   * 扫描项目截图
   */
  private scanProjectScreenshots(project: any, resources: ResourceInfo[]): void {
    if (!project.screenshot) return;

    const screenshotUrl = typeof project.screenshot === 'string'
      ? project.screenshot
      : project.screenshot?.url;

    if (screenshotUrl) {
      const resource = this.createResourceInfo(screenshotUrl, 'project_screenshot');
      resources.push(resource);
    }
  }

  /**
   * 扫描项目资源包
   */
  private scanProjectAssets(project: any, resources: ResourceInfo[]): void {
    if (!project.assets || !Array.isArray(project.assets)) return;

    project.assets.forEach((asset: any) => {
      if (asset.package?.urls && Array.isArray(asset.package.urls)) {
        asset.package.urls.forEach((url: string) => {
          if (url && typeof url === 'string') {
            const resource = this.createResourceInfo(url, 'asset_package');
            resources.push(resource);
          }
        });
      }
    });
  }

  /**
   * 扫描项目文档列表（简化版）
   */
  private scanProjectDocuments(project: any, resources: ResourceInfo[]): void {
    if (!project.documents || !Array.isArray(project.documents)) return;

    project.documents.forEach((doc: any) => {
      if (doc.screenshot) {
        const screenshotUrl = typeof doc.screenshot === 'string'
          ? doc.screenshot
          : doc.screenshot?.url;

        if (screenshotUrl) {
          const resource = this.createResourceInfo(screenshotUrl, 'document_screenshot');
          resources.push(resource);
        }
      }
    });
  }

  /**
   * 扫描文档中的资源
   */
  private scanDocumentResources(document: any, resources: ResourceInfo[]): void {
    // 扫描 schema 中的资源
    if (document.schema) {
      this.scanSchemaResources(document.schema, resources);
    }

    // 扫描其他可能包含资源的字段
    this.scanFieldResources(document, 'poster', resources);
    this.scanFieldResources(document, 'icon', resources);
    this.scanAssetsResources(document, resources);
  }

  /**
   * 扫描 schema 中的资源（支持字符串和对象形式）
   */
  private scanSchemaResources(schema: any, resources: ResourceInfo[]): void {
    let schemaString: string;

    if (typeof schema === 'string') {
      schemaString = schema;
    } else if (typeof schema === 'object') {
      schemaString = JSON.stringify(schema);
    } else {
      return;
    }

    // 使用正则表达式提取所有URL（更精确的匹配）
    const urlRegex = /https?:\/\/[^\s"'`}\]]+(?=["'\s\)}`}\]]|$)/g;
    let matches = schemaString.match(urlRegex) as string[];

    // 后处理：确保URL完整性
    if (matches && matches.length > 0) {
      matches = matches.map(url => {
        // 移除可能的尾部字符
        url = url.replace(/["'}\]\)]+$/, '');

        // 对于Unsplash URL，确保完整性
        if (url.includes('unsplash.com/photo-')) {
          // 检查是否被截断，尝试找到完整URL
          const startIndex = schemaString.indexOf(url);
          if (startIndex !== -1) {
            const remainingText = schemaString.substring(startIndex);
            const fullUrlMatch = remainingText.match(/https?:\/\/[^\s"'`}\]]+/) as string[];
            if (fullUrlMatch && fullUrlMatch.length > 0) {
              url = fullUrlMatch[0].replace(/["'}\]\)]+$/, '');
            }
          }
        }

        return url;
      });
    }

    if (matches) {
      matches.forEach(url => {
        const resource = this.createResourceInfo(url, 'schema_content');
        resources.push(resource);
      });
    }
  }

  /**
   * 扫描字段中的资源
   */
  private scanFieldResources(obj: any, fieldName: string, resources: ResourceInfo[]): void {
    if (!obj || !obj[fieldName]) return;

    const fieldValue = obj[fieldName];
    if (typeof fieldValue === 'string') {
      const resource = this.createResourceInfo(fieldValue, fieldName);
      resources.push(resource);
    }
  }

  /**
   * 扫描文档的资源列表
   */
  private scanAssetsResources(document: any, resources: ResourceInfo[]): void {
    if (!document.assets || !Array.isArray(document.assets)) return;

    document.assets.forEach((asset: any) => {
      // 这里可以根据实际的 assets 结构进行调整
      if (asset.package?.urls) {
        asset.package.urls.forEach((url: string) => {
          if (url && typeof url === 'string') {
            const resource = this.createResourceInfo(url, 'document_asset');
            resources.push(resource);
          }
        });
      }
    });
  }

  /**
   * 创建资源信息对象
   */
  private createResourceInfo(url: string, sourceType: string): ResourceInfo {
    // 判断是否为CDN资源（包括hash值类型）
    const isCdn = url.includes(cdnDomain) || this.isQiniuHash(url);
    const pathInProject = this.extractPathFromUrl(url);
    const type = this.detectResourceType(url);

    return {
      originalUrl: url,
      localPath: this.generateLocalPath(url, sourceType),
      type,
      source: isCdn ? 'cdn' : 'external',
      pathInProject: pathInProject,
    };
  }

  /**
   * 判断是否为七牛云hash值
   */
  private isQiniuHash(url: string): boolean {
    // 七牛云hash通常是20-40位，包含字母、数字、下划线和连字符
    const qiniuHashPattern = /^[A-Za-z0-9_-]{20,}$/;
    return qiniuHashPattern.test(url) && !url.includes('/') && !url.includes('.');
  }

  /**
   * 从URL中提取路径
   */
  private extractPathFromUrl(url: string): string {
    try {
      const urlObj = new URL(url);
      return urlObj.pathname;
    } catch {
      // 如果不是完整的URL，可能是七牛云的hash或相对路径
      if (/^[A-Za-z0-9_-]{15,}$/.test(url)) {
        // 纯hash，直接返回
        return url;
      }
      // 相对路径，直接返回
      return url;
    }
  }

  /**
   * 生成本地存储路径
   */
  private generateLocalPath(url: string, sourceType: string): string {
    const pathInProject = this.extractPathFromUrl(url);
    const extension = this.getFileExtension(url);
    const type = this.detectResourceType(url);

    // 判断URL类型
    if (/^[A-Za-z0-9_-]{15,}$/.test(url)) {
      // 纯hash：保持原样，如 FuoPS2xYMgbdOYHtwkWITu0RmaKR
      return `resources/${type}/${url}`;
    } else if (url.startsWith('/')) {
      // 相对路径：保持路径结构，如 /a/b/c -> resources/type/a/b/c
      return `resources/${type}${pathInProject}`;
    } else {
      // 完整URL：提取路径部分，如 https://cdn.appthen.com/a/b/c -> resources/type/a/b/c
      return `resources/${type}${pathInProject}`;
    }
  }

  /**
   * 检测资源类型
   */
  private detectResourceType(url: string): ResourceType {
    const extension = this.getFileExtension(url).toLowerCase();
    const path = url.toLowerCase();

    if (path.includes('image') || ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.svg', '.bmp'].includes(extension)) {
      return ResourceType.IMAGE;
    }
    if (path.includes('script') || ['.js', '.mjs'].includes(extension)) {
      return ResourceType.SCRIPT;
    }
    if (path.includes('style') || ['.css', '.scss', '.sass', '.less'].includes(extension)) {
      return ResourceType.STYLE;
    }
    if (path.includes('font') || ['.woff', '.woff2', '.ttf', '.eot', '.otf'].includes(extension)) {
      return ResourceType.FONT;
    }
    if (['.mp4', '.avi', '.mov', '.wmv', '.flv', '.webm'].includes(extension)) {
      return ResourceType.VIDEO;
    }
    if (['.mp3', '.wav', '.ogg', '.aac', '.flac'].includes(extension)) {
      return ResourceType.AUDIO;
    }

    return ResourceType.OTHER;
  }

  /**
   * 获取文件扩展名
   */
  private getFileExtension(url: string): string {
    try {
      const urlObj = new URL(url);
      const path = urlObj.pathname;
      const lastDot = path.lastIndexOf('.');
      return lastDot > -1 ? path.substring(lastDot) : '';
    } catch {
      // 如果不是完整URL，直接从字符串中提取
      const lastDot = url.lastIndexOf('.');
      return lastDot > -1 ? url.substring(lastDot) : '';
    }
  }

  /**
   * 资源去重
   */
  private deduplicateResources(resources: ResourceInfo[]): ResourceInfo[] {
    const seen = new Set<string>();
    return resources.filter(resource => {
      const key = resource.originalUrl;
      if (seen.has(key)) {
        return false;
      }
      seen.add(key);
      return true;
    });
  }
}